package com.springcloud.demo.service;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.springcloud.demo.pojo.Order;
import com.springcloud.demo.pojo.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * @Author: XiaoJie Wang
 * @Description:
 * @Date: Create in 16:59 2021/7/8
 */
@Service
public class OrderServiceImpl implements OrderService{

    @Resource(name = "restTemplate")
    private RestTemplate restTemplate;

    @Autowired
    private ProductService productService;


    @Override
    public Order selectOrderByIdTemplate(Integer id) {
        return new Order(id, "order-rest", "中国-China", 31996D,
                Arrays.asList(selectProductListByLoadBalancerAnnotation()));
    }

    @Override
//    @SentinelResource(value = "selectOrderByIdFeign",
//            blockHandler = "selectOrderByIdFeignBlockHandler",
//            fallback = "selectOrderByIdFeignFallback")
    public Order selectOrderByIdFeign(Integer id, String productName) {
        // 模拟查询主键为 1 的商品信息会导致异常
       if (1 == id)
           throw new RuntimeException("查询主键为 1 的订单信息导致异常");
        return new Order(id, "order-feign", "中国-China", 31996D,
                Arrays.asList(productService.selectProductById(1)));
    }

    // 服务流量控制处理，参数最后多一个 BlockException，其余与原函数一致。
    public Order selectOrderByIdFeignBlockHandler(Integer id,String productName, BlockException ex) {
        // Do some log here.
        ex.printStackTrace();
        return new Order(id, "服务流量控制处理-托底数据", "中国", 2666D,
                Arrays.asList(productService.selectProductById(1)));
    }

    // 服务熔断降级处理，函数签名与原函数一致或加一个 Throwable 类型的参数
    public Order selectOrderByIdFeignFallback(Integer id, String productName,Throwable throwable) {
        System.out.println("sentinel-service 服务的 selectOrderByIdFeign 方法出现异常，异常信息如下："
                + throwable);
        return new Order(id, "服务熔断降级处理-托底数据", "中国", 2666D,
                Arrays.asList(productService.selectProductById(1)));
    }
    

    private Product selectProductListByLoadBalancerAnnotation() {
        // ResponseEntity: 封装了返回数据
        ResponseEntity<Product> response = restTemplate.exchange(
                "http://service-provider/product/1",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<Product>() {});
        System.out.println(response.getHeaders().getLocation());
        return response.getBody();
    }
}
